/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.zakariya.stickyheaders;

import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.app.Context;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;
import org.zakariya.stickyheaders.callback.ClickCallback;
import org.zakariya.stickyheaders.model.ItemModel;

import java.util.List;
/**
 * StickyHeaderLayoutManager
 *
 * @since 2021-08-20
 */
public class StickyHeaderLayoutManager {
    private static final int UPSCROLL = 1;
    private static final int DOWNSCROLL = 2;
    private ListContainer listContainer;
    /**
     * tab显示状态，true正常状态
     */
    private static boolean isTabChanged = true;
    private Text headerText;
    private Text indexText;
    private float headerTextY = 0;
    private int scrollType = 0;
    private Button collapse;
    private Button cloneBtn;
    private Button deleteBtn;
    private DependentLayout overlapLayout;
    private ClickCallback clickCallback;
    /**
     * onTouchEvent事件中记录down时的Y轴值
     */
    private float mDownY = 0;
    private List<ItemModel> dataList;
    /**
     * 下滑时是否要更改上方悬停标题
     */
    private boolean isChangeTitle = false;
    /**
     * 单头部显示的字符串
     */
    private String headerString = "0";
    /**
     * 单头部显示的字符串
     */
    private String headerIndex = "0";

    private DependentLayout layout_sticky_header;
    private Context mContext;
    private int index;
    private boolean showHeadSection;

    /**
     * 单header构造函数
     *
     * @param listContainer 滑动控件
     * @param oneText       头部Header
     */
    public StickyHeaderLayoutManager(ListContainer listContainer, Text oneText, DependentLayout overlapLayout) {
        this.listContainer = listContainer;
        this.headerText = oneText;
        this.headerTextY = headerText.getHeight();
        this.overlapLayout = overlapLayout;
        setTouchEventLisener();
        setScrolledListener();
    }

    /**
     * 单header构造函数
     *
     * @param listContainer 滑动控件
     * @param oneText       头部Header
     */
    public StickyHeaderLayoutManager(ListContainer listContainer,
                                     DependentLayout layout_overlap, Text oneText, Text indexText) {
        this.listContainer = listContainer;
        this.headerText = oneText;
        this.indexText = indexText;
        this.overlapLayout = layout_overlap;
        this.headerTextY = headerText.getHeight();
        setTouchEventLisener();
        setScrolledListener();
    }

    /**
     * StickyHeaderLayoutManager
     *
     * @param listContainer        listContainer
     * @param oneText              oneText
     * @param indexText            indexText
     * @param layout_sticky_header layout_sticky_header
     * @param context              context
     */
    public StickyHeaderLayoutManager(ListContainer listContainer, Text oneText, Text indexText,
                                     DependentLayout layout_sticky_header, Context context) {
        this.listContainer = listContainer;
        this.headerText = oneText;
        this.indexText = indexText;
        this.headerTextY = headerText.getHeight();
        this.layout_sticky_header = layout_sticky_header;
        this.overlapLayout = layout_sticky_header;
        this.mContext = context;
        setTouchEventLisener();
        setScrolledListener();
    }

    /**
     * 单header构造函数
     *
     * @param listContainer  滑动控件
     * @param oneText        头部Header
     * @param mClickCallback mClickCallback
     */
    public StickyHeaderLayoutManager(ListContainer listContainer, DependentLayout layout_overlap, Text oneText,
                                     Text indexText, Button collapse, ClickCallback mClickCallback) {
        this.listContainer = listContainer;
        this.headerText = oneText;
        this.indexText = indexText;
        this.collapse = collapse;
        this.headerTextY = headerText.getHeight();
        this.overlapLayout = layout_overlap;
        this.clickCallback = mClickCallback;
        setTouchEventLisener();
        setScrolledListener();
        setClickedListener();
    }

    /**
     * 单header构造函数
     *
     * @param listContainer 滑动控件
     * @param oneText       头部Header
     */
    public StickyHeaderLayoutManager(ListContainer listContainer, DependentLayout layout_overlap, Text oneText, Text indexText,
                                     Button cloneBtn, Button deleteBtn, ClickCallback mClickCallback) {
        this.listContainer = listContainer;
        this.headerText = oneText;
        this.indexText = indexText;
        this.cloneBtn = cloneBtn;
        this.deleteBtn = deleteBtn;
        this.overlapLayout = layout_overlap;
        this.clickCallback = mClickCallback;
        this.headerTextY = headerText.getHeight();
        setTouchEventLisener();
        setScrolledListener();
        setClickedListener();
    }

    private void setClickedListener() {
        if (collapse != null) {
            collapse.setClickedListener(component -> clickCallback.onClick(index, ActionType.TOGGLE, Constant.ISOTHER, collapse));
        }
        if (cloneBtn != null) {
            cloneBtn.setClickedListener(component -> clickCallback.onClick(index, ActionType.CLONE, Constant.ISOTHER, null));
        }
        if (deleteBtn != null) {
            deleteBtn.setClickedListener(component -> clickCallback.onClick(index, ActionType.DELETE, Constant.ISOTHER, null));
        }
    }

    /**
     * 监听tab页状态类
     *
     * @since 2021-04-25
     */
    public static class MyTabListener implements TabItemChangeListener {
        @Override
        public void onTabChangeStatus(boolean status) {
            isTabChanged = status;
        }
    }

    /**
     * 设置数据
     *
     * @since 2021-04-25
     */
    public void setDataList(List<ItemModel> dataList, boolean showHeadSection) {
        this.dataList = dataList;
        this.showHeadSection = showHeadSection;
    }

    private void setTouchEventLisener() {
        listContainer.setTouchEventListener((component, touchEvent) -> {
            int action = touchEvent.getAction();
            MmiPoint point = touchEvent.getPointerPosition(touchEvent.getIndex());
            switch (action) {
                case TouchEvent.PRIMARY_POINT_DOWN:
                    return true;
                case TouchEvent.POINT_MOVE:
                    if (point.getY() > mDownY) {
                        scrollType = DOWNSCROLL;
                    } else if (point.getY() < mDownY) {
                        scrollType = UPSCROLL;
                    }
                    mDownY = point.getY();
                    break;
                case TouchEvent.PRIMARY_POINT_UP:
                    mDownY = 0;
                    break;
                case TouchEvent.NONE:
                case TouchEvent.CANCEL:
                    mDownY = point.getY();
                    return true;
                default:
                    break;
            }
            return false;
        });
    }

    private void setScrolledListener() {
        listContainer.setScrolledListener((component, scrollX, scrollY, oldScrollX, oldScrollY) -> {
            if (!isTabChanged) {
                return;
            }
            if (scrollType == DOWNSCROLL) {
                downMove();
            } else if (scrollType == UPSCROLL) {
                upMove();
            } else {
                //非手动滑动时候的事件处理
                handleScollEvent();
            }
        });
    }

    private void handleScollEvent() {
        int index = listContainer.getItemPosByVisibleIndex(0);
        setViewVisible();
        ItemModel itemModel = null;
        itemModel = dataList.get(index);
        for (int i = 0; i < dataList.size(); i++) {
            if (dataList.get(i).isHeader()) {
                if (dataList.get(i).getTitle().equals(itemModel.getTitle())
                        || itemModel.getTitle().substring(0, 1).equals(dataList.get(i).getTitle())) {
                    headerText.setText(dataList.get(i).getTitle());
                    if (indexText != null) {
                        if (!showHeadSection) {
                            indexText.setText(dataList.get(i).getIndex() + "");
                        } else {
                            indexText.setText(dataList.get(i).getHeadSection() + "");
                        }
                    }
                }
            }
        }
    }

    /**
     * 向下滑动
     */
    private void downMove() {
        int firstIndex = listContainer.getItemPosByVisibleIndex(0);
        if (firstIndex < 0 || firstIndex >= dataList.size()) {
            return;
        }
        index = listContainer.getItemPosByVisibleIndex(1);
        if (index < 0 || index >= dataList.size()) {
            return;
        }
        boolean isHeader = dataList.get(index).isHeader();
        Component firstView = listContainer.getComponentAt(index);
        if (firstView == null) {
            return;
        }
        int firstViewTop = firstView.getTop();
        if (firstIndex == 0) {
            if (!dataList.get(0).isHeader()) {
                setViewHide();
            } else {
                if (firstViewTop >= headerTextY) {
                    setViewHide();
                }
            }
            return;
        }
        if (isHeader) {
            isChangeTitle = true;
            float moveY = firstViewTop - headerTextY;
            if (moveY <= 0) {
                setContentPositionY(moveY);
            }
            for (int i = index - 1; i >= 0; i--) {
                if (dataList.get(i).isHeader()) {
                    if (layout_sticky_header != null) {
                        headerString = "SECTION: " + dataList.get(i).getTitle();
                    } else {
                        headerString = dataList.get(i).getTitle();
                    }
                    if (!showHeadSection) {
                        headerIndex = dataList.get(i).getIndex() + "";
                    } else {
                        headerIndex = dataList.get(i).getHeadSection() + "";
                    }
                    break;
                }
            }
            if (indexText != null) {
                indexText.setText(headerIndex);
            }
            headerText.setText(headerString);
        } else {
            if (isChangeTitle && index != 0) {
                headerText.setText(headerString);
                if (indexText != null) {
                    indexText.setText(headerIndex);
                }
            }
            setContentPositionY(0);
            isChangeTitle = false;
        }
    }

    /**
     * 设置控件显隐
     */
    private void setViewHide() {
        if (overlapLayout != null) {
            overlapLayout.setVisibility(Component.HIDE);
        } else {
            headerText.setVisibility(Component.HIDE);
            if (indexText != null) {
                indexText.setVisibility(Component.HIDE);
            }
        }
    }

    /**
     * 设置控件显隐
     */
    private void setViewVisible() {
        if (overlapLayout != null) {
            overlapLayout.setVisibility(Component.VISIBLE);
        } else {
            headerText.setVisibility(Component.VISIBLE);
            if (indexText != null) {
                indexText.setVisibility(Component.VISIBLE);
            }
        }
    }

    /**
     * 向上滑动
     */
    private void upMove() {
        // 获取当前屏幕完整显示的第1个item的下标
        index = listContainer.getItemPosByVisibleIndex(1);
        if (index < 0 || index >= dataList.size()) {
            return;
        }
        boolean isHeader = dataList.get(index).isHeader();
        Component firstView = listContainer.getComponentAt(index);
        if (firstView == null) {
            return;
        }
        int firstViewTop = firstView.getTop();
        if (index == 1 && firstViewTop <= headerTextY) {
            if (dataList.get(0).isHeader()) {
                headerText.setText(dataList.get(0).getTitle());
                if (!showHeadSection) {
                    headerIndex = dataList.get(0).getIndex() + "";
                } else {
                    headerIndex = dataList.get(0).getHeadSection() + "";
                }
                setViewVisible();
                if (indexText != null) {
                    indexText.setText(headerIndex);
                }
            }
        } else {
            setViewVisible();
            ItemModel itemModel = null;
            itemModel = dataList.get(index);
            if (itemModel.isHeader()) {
                for (int i = 0; i < dataList.size(); i++) {
                    if (dataList.get(i).getTitle().equals(itemModel.getTitle())) {
                        headerText.setText(dataList.get(i).getTitle());
                        if (indexText != null) {
                            if (showHeadSection) {
                                indexText.setText(dataList.get(i).getHeadSection() + "");
                            }
                        }
                    }
                }
            }
        }

        if (isHeader) {
            isChangeTitle = true;
            float moveY = firstViewTop - headerTextY;
            if (moveY <= 0) {
                setContentPositionY(moveY);
            }
            ItemModel itemModel = null;
            itemModel = dataList.get(index);
            if (itemModel != null) {
                headerString = itemModel.getTitle();
                if (!showHeadSection) {
                    headerIndex = itemModel.getIndex() + "";
                } else {
                    headerIndex = itemModel.getHeadSection() + "";
                }
            }
        } else {
            if (isChangeTitle && index != 0) {
                headerText.setText(headerString);
                if (indexText != null) {
                    indexText.setText(headerIndex);
                }
            }
            setContentPositionY(0);
            isChangeTitle = false;
        }
    }

    /**
     * setContentPositionY
     *
     * @param moveY
     */
    private void setContentPositionY(float moveY) {
        headerText.setContentPositionY(moveY);
        headerText.setText(dataList.get(index - 1).getTitle());
        if (layout_sticky_header != null && moveY == 0) {
            headerText.setText("SECTION: " + dataList.get(index).getTitle());
            if (Integer.parseInt(dataList.get(index).getTitle()) % 2 == 0) {
                headerText.setBackground(new ShapeElement(mContext, ResourceTable.Graphic_background_multiple_item_1));
            } else {
                headerText.setBackground(new ShapeElement(mContext, ResourceTable.Graphic_background_multiple_item_2));
            }
        } else if (layout_sticky_header != null && moveY != 0) {
            headerText.setText("SECTION: " + (Integer.parseInt(dataList.get(index).getTitle()) - 1));
        }

        if (indexText != null) {
            indexText.setContentPositionY(moveY);
            if (showHeadSection) {
                indexText.setText(dataList.get(index - 1).getHeadSection() + "");
            }

        }
        if (collapse != null) {
            collapse.setContentPositionY(moveY);
        }
        if (cloneBtn != null) {
            cloneBtn.setContentPositionY(moveY);
        }
        if (deleteBtn != null) {
            deleteBtn.setContentPositionY(moveY);
        }
    }

}
